package RiskAlert;

import java.util.Arrays;

/**
 * SAGM(1,1)-Self Adjusting Grey Model
 * 自校正灰色预测模型
 * 在实际应用时需要修改selectChildData方法、divideInput方法
 * @author paddy
 *
 */
public class SAGM {

	private static double OriginData[]=new double[3];//原始数据序列
	private static double ChildData[][];//不同长度的子数据序列,对所有子序列进行初始化处理操作，实际应用时根据预测时间的长短选取其中一个子序列即可
	private static double input[];//AS，为了最终预测所选取的某一子序列
	private static double intput1[];//BS，按照时间顺序依次划分的两个互不相交的子集中，前半部分
	private static double input2[];//PS，后半部分


	static{
		if(OriginData.length<4){
			System.out.println("原始数据不足，请重新修改！");
			System.exit(-1);
		}
		else{
			ChildData=new double[OriginData.length-3][];
			for(int i=0;i<OriginData.length;i++)
				OriginData[i]=i;
		}
		if(OriginData.length==4)
			ChildData[0]=Arrays.copyOf(OriginData, OriginData.length);
		else{
			int j=0;
			while(j<OriginData.length-3)
				ChildData[j]=Arrays.copyOfRange(OriginData, ++j, OriginData.length);
		}
	}

	/**
	 * 对原始数据序列进行处理，产生子数据序列
	 * @param OD
	 * @return
	 */
	public boolean getChildData(double[] OD){

		if(OD.length<4)
			return false;
		int i=0;
		for(;i<OD.length-4;i++){
			ChildData[i]=Arrays.copyOfRange(OD, i+1, OD.length);
		}
		return true;
	}

	/**
	 * 对子数据序列进行处理，初始化为直接可用的子数据序列
	 * 处理的结果作为下一步利用滑动平均法进行处理的数据输入
	 * @param CD
	 * @return
	 */
	public boolean InitChildData(double[][] CD){

		double c[]=new double[ChildData.length];
		double temp = 0;
		for(int i=0;i<ChildData.length;i++){
			for(int j=0;j<ChildData[i].length;j++){
				temp=ChildData[i][j];
				temp=Math.min(temp,ChildData[i][j]);
			}
			if(temp<0)
				c[i]=0;
			else
				c[i]=temp+1;
		}
		for(int i=0;i<c.length;i++)
			for(int j=0;j<ChildData[i].length;j++)
				ChildData[i][j]=ChildData[i][j]+c[i];
		return true;
	}

	/**
	 * 利用滑动平均法抑制数据序列的过渡波动
	 * 进一步对子数据序列进行处理
	 * @param CD
	 * @return
	 */
	public boolean handleChildData(double[][] CD){

		for(int i=0;i<ChildData.length;i++){
			int length=ChildData[i].length;
			ChildData[i][0]=(3*ChildData[i][0]+ChildData[i][1])/4;  //处理始端数据
			ChildData[i][length-1]=(ChildData[i][length-2]+3*ChildData[i][length-1])/4;//处理尾端数据
			
			//处理端点之外的其他数据
			for(int j=1;j<ChildData[i].length-1;j++){
				ChildData[i][j]=(ChildData[i][j-1]+2*ChildData[i][j]+ChildData[i][j+1])/4;
			}
		}
		
		return true;
	}

	/**
	 * 根据预测时间的长短选取某一子序列
	 * 实际应用中需要根据预测时间的长短进行选择，这里模拟随机选取
	 * @param ChildData
	 * @return
	 */
	public boolean selectChildData(double[][] CD){
		
		int temp=(int)Math.random()*(ChildData.length-1);
		
		input=Arrays.copyOf(ChildData[temp],ChildData[temp].length);
		
		return true;
	}
	
	/**
	 * 按照时间顺序一次划分成两个互不相交的子集
	 * 实际应用中需要根据时间顺序进行选取，这里仅做模拟，各划分一半
	 * @param input
	 * @return
	 */
	public boolean divideInput(double[] input){
		
		int average=input.length/2;
		intput1=Arrays.copyOfRange(input, 0, average-1);
		
		return true;
	}
	
	/**
	 * 利用划分的子序列的前半部分建立GM(1,1)基本模型
	 * @param input1
	 * @return
	 */
	public boolean buildBaseModel(double[] input1){
		return true;
	}
	
	public static void main(String[] args) {
		//				RA ra=new RA();
		//				ra.getChildData(OriginData);
		//		for(int i=0;i<ChildData.length;i++){
		//			for(int j=0;j<ChildData[i].length;j++)
		//				System.out.print(ChildData[i][j]+" ");
		//			System.out.println();
		//		}
	}
}
